use std::sync::Arc;
use actix_web::{web, HttpRequest, HttpResponse};

use log::info;
use sea_orm::DatabaseConnection;

use crate::utils::transaction_util::handle_transaction;
use policy::services::policy_service::PolicyService;

/// Adds a new policy to the system.
///
/// # Parameters
/// * `req` - The HTTP request containing authentication and context information
/// * `db` - Database connection wrapped in web::Data
/// * `req_body` - JSON payload containing the policy data
///
/// # Returns
/// * `HttpResponse` - Response indicating success or failure of the operation
pub async fn add_policy(req: HttpRequest, db: web::Data<Arc<DatabaseConnection>>, req_body: web::Json<serde_json::Value>) -> HttpResponse {
    info!("Received request to add policy");
    handle_transaction(db, |txn| PolicyService::add_policy(req, txn, req_body)).await
}

/// Updates an existing policy in the system.
///
/// # Parameters
/// * `req` - The HTTP request containing authentication and context information
/// * `db` - Database connection wrapped in web::Data
/// * `req_body` - JSON payload containing the updated policy data
///
/// # Returns
/// * `HttpResponse` - Response indicating success or failure of the operation
pub async fn update_policy(req: HttpRequest, db: web::Data<Arc<DatabaseConnection>>, req_body: web::Json<serde_json::Value>) -> HttpResponse {
    info!("Received request to update policy");
    handle_transaction(db, |txn| PolicyService::update_policy(req, txn, req_body)).await
}

/// Deletes an existing policy from the system.
///
/// # Parameters
/// * `req` - The HTTP request containing authentication and context information
/// * `db` - Database connection wrapped in web::Data
/// * `req_body` - JSON payload containing the policy identifier
///
/// # Returns
/// * `HttpResponse` - Response indicating success or failure of the operation
pub async fn delete_policy(req: HttpRequest, db: web::Data<Arc<DatabaseConnection>>, req_body: web::Json<serde_json::Value>) -> HttpResponse {
    info!("Received request to delete policy");
    handle_transaction(db, |txn| PolicyService::delete_policy(req, txn, req_body)).await
}

/// Queries policies based on provided parameters.
///
/// # Parameters
/// * `req` - The HTTP request containing authentication and query parameters
/// * `db` - Database connection wrapped in web::Data
///
/// # Returns
/// * `HttpResponse` - Response containing the query results or error message
pub async fn query_policy(req: HttpRequest, db: web::Data<Arc<DatabaseConnection>>) -> HttpResponse {
    info!("Received request to query policy");
    let query_params = web::Query::<serde_json::Value>::from_query(req.query_string()).unwrap_or_else(|_| web::Query(serde_json::json!({})));
    handle_transaction(db, |txn| PolicyService::query_policy(req, txn, web::Json(query_params.0))).await
}
